#include "StdAfx.h"
#include "TrackLoader.h"
#include "RenderableObject.h"
#include "ActionObject.h"
#include "CollisionController.h"
#include "RenderingManager.h"
#include "MeshStorage.h"
#include "PhysicalObject.h"
#include "PlayersManager.h"
#include "AIAgent.h"
#include "Gate.h"


/////////////////////////////////////////////////////////////////////////////

TrackLoader::TrackLoader(CCollisionController& collisionController,
                         IRenderingManager& renderingManager,
                         IMeshStorage& meshStorage,
                         IPlayersManager& playersManager,
                         IRaceController& raceController,
                         std::vector<ActionObject*>& activePlayers,
                         std::vector<Gate*>& gates,
                         std::vector<AIAgent*>& aiAgents)
      : m_collisionController(collisionController),
      m_renderingManager(renderingManager),
      m_meshStorage(meshStorage),
      m_playersManager(playersManager),
      m_raceController(raceController),
      m_activePlayers(activePlayers),
      m_gates(gates),
      m_aiAgents(aiAgents),
      m_controlledPhysicalObject(NULL),
      m_controlledActionObject(NULL),
      m_controlledMovable(NULL)
{
}

/////////////////////////////////////////////////////////////////////////////

void TrackLoader::load(const std::string& trackName)
{
   // load map
   AABoundingBox worldBounds;
   worldBounds.min = D3DXVECTOR3(50, -5, 50);
   worldBounds.max = D3DXVECTOR3(1950, 5, 1950);
   m_collisionController.setWorldBounds(worldBounds);

   if (trackName == "easy")
   {
      m_collisionController.setScenery(m_meshStorage.getTerrainScenery(trackName));
      m_renderingManager.startRendering(m_meshStorage.getTerrainRenderable(trackName));

      addPlayer(D3DXVECTOR3(419, 0, 1016));
      addEnemy(D3DXVECTOR3(447, 0, 1016));
      addEnemy(D3DXVECTOR3(474, 0, 1016));
      addEnemy(D3DXVECTOR3(502, 0, 1016));

      addGate(D3DXVECTOR3(392, 0, 1016), D3DXVECTOR3(528, 0, 1016));
      addGate(D3DXVECTOR3(544, 0, 1592), D3DXVECTOR3(656, 0, 1536));
      addGate(D3DXVECTOR3(1032, 0, 1912), D3DXVECTOR3(1032, 0, 1776));
      addGate(D3DXVECTOR3(1504, 0, 1600), D3DXVECTOR3(1408, 0, 1528));
      addGate(D3DXVECTOR3(1664, 0, 1024), D3DXVECTOR3(1536, 0, 1024));
      addGate(D3DXVECTOR3(1424, 0, 568), D3DXVECTOR3(1536, 0, 520));
      addGate(D3DXVECTOR3(1024, 0, 280), D3DXVECTOR3(1024, 0, 152));
      addGate(D3DXVECTOR3(544, 0, 472), D3DXVECTOR3(648, 0, 528));
  
   }
   else if (trackName == "difficult")
   {
      m_collisionController.setScenery(m_meshStorage.getTerrainScenery(trackName));
      m_renderingManager.startRendering(m_meshStorage.getTerrainRenderable(trackName));

      addPlayer(D3DXVECTOR3(176, 0, 344));
      addEnemy(D3DXVECTOR3(200, 0, 344));
      addEnemy(D3DXVECTOR3(224, 0, 344));
      addEnemy(D3DXVECTOR3(248, 0, 344));

      addGate(D3DXVECTOR3(152, 0, 344), D3DXVECTOR3(272, 0, 368));      
      addGate(D3DXVECTOR3(128, 0, 1040), D3DXVECTOR3(264, 0, 1040));    
      addGate(D3DXVECTOR3(328, 0, 1256), D3DXVECTOR3(328, 0, 1112));    
      addGate(D3DXVECTOR3(592, 0, 1208), D3DXVECTOR3(680, 0, 1104));    
      addGate(D3DXVECTOR3(352, 0, 1624), D3DXVECTOR3(496, 0, 1584));    
      addGate(D3DXVECTOR3(1488, 0, 1808), D3DXVECTOR3(1408, 0, 1696));  
      addGate(D3DXVECTOR3(1400, 0, 1648), D3DXVECTOR3(1376, 0, 1536));  
      addGate(D3DXVECTOR3(928, 0, 1288), D3DXVECTOR3(1064, 0, 1288));   
      addGate(D3DXVECTOR3(1144, 0, 1056), D3DXVECTOR3(1152, 0, 1160));  
      addGate(D3DXVECTOR3(1512, 0, 1432), D3DXVECTOR3(1584, 0, 1336));  
      addGate(D3DXVECTOR3(1872, 0, 1392), D3DXVECTOR3(1784, 0, 1312));  
      addGate(D3DXVECTOR3(1856, 0, 944), D3DXVECTOR3(1968, 0, 864));    
      addGate(D3DXVECTOR3(1736, 0, 864), D3DXVECTOR3(1792, 0, 960));    
      addGate(D3DXVECTOR3(1464, 0, 1016), D3DXVECTOR3(1536, 0, 920));   
      addGate(D3DXVECTOR3(1408, 0, 776), D3DXVECTOR3(1528, 0, 808));    
      addGate(D3DXVECTOR3(1656, 0, 496), D3DXVECTOR3(1776, 0, 512));    
      addGate(D3DXVECTOR3(1608, 0, 352), D3DXVECTOR3(1680, 0, 272));    
      addGate(D3DXVECTOR3(1176, 0, 200), D3DXVECTOR3(1184, 0, 80));     
      addGate(D3DXVECTOR3(904, 0, 280), D3DXVECTOR3(800, 0, 248));      
      addGate(D3DXVECTOR3(960, 0, 536), D3DXVECTOR3(1016, 0, 424));     
      addGate(D3DXVECTOR3(1168, 0, 640), D3DXVECTOR3(1288, 0, 624));    
      addGate(D3DXVECTOR3(1104, 0, 752), D3DXVECTOR3(1184, 0, 840));    
      addGate(D3DXVECTOR3(688, 0, 888), D3DXVECTOR3(752, 0, 792));      
      addGate(D3DXVECTOR3(520, 0, 360), D3DXVECTOR3(632, 0, 336));      
      addGate(D3DXVECTOR3(400, 0, 256), D3DXVECTOR3(400, 0, 144)); 
   }
}

/////////////////////////////////////////////////////////////////////////////

void TrackLoader::addPlayer(const D3DXVECTOR3& position)
{
   D3DMATERIAL9 material;
   ZeroMemory(&material.Ambient, sizeof(material.Ambient));
   ZeroMemory(&material.Specular, sizeof(material.Specular));
   ZeroMemory(&material.Emissive, sizeof(material.Emissive));
   material.Diffuse.r = 1.0f; material.Diffuse.g = 0.8f; material.Diffuse.b = 0.6f;


   CRenderableObject* renderableAvatar = new CRenderableObject(m_meshStorage.getCarMesh(), material);
   renderableAvatar->move(position);
   PhysicalObject& movableAvatar = m_collisionController.addMovable(*renderableAvatar);
   movableAvatar.setAcceleration(200);
   movableAvatar.setMaxHorizontalSpeed(250);
   movableAvatar.setMaxVerticalSpeed(100);
   movableAvatar.setWeight(20);
   movableAvatar.setFriction(250);

   m_controlledPhysicalObject = &movableAvatar;
   m_controlledMovable = renderableAvatar;
   
   m_controlledActionObject = new ActionObject(m_playersManager, m_renderingManager, 
                                       new CRenderableObject(m_meshStorage.getLaserMesh(), D3DMATERIAL9()), 
                                       renderableAvatar);
   m_activePlayers.push_back(m_controlledActionObject);
}

/////////////////////////////////////////////////////////////////////////////

void TrackLoader::addEnemy(const D3DXVECTOR3& position)
{
   D3DMATERIAL9 material;
   ZeroMemory(&material.Ambient, sizeof(material.Ambient));
   ZeroMemory(&material.Specular, sizeof(material.Specular));
   ZeroMemory(&material.Emissive, sizeof(material.Emissive));
   material.Diffuse.r = 1.0f; material.Diffuse.g = 0.8f; material.Diffuse.b = 0.6f;


   CRenderableObject* renderableEnemy = new CRenderableObject(m_meshStorage.getCarMesh(), material);
   renderableEnemy->move(position);
   PhysicalObject& movableEnemy = m_collisionController.addMovable(*renderableEnemy);

   movableEnemy.setAcceleration(200);
   movableEnemy.setMaxHorizontalSpeed(250);
   movableEnemy.setMaxVerticalSpeed(100);
   movableEnemy.setWeight(20);
   movableEnemy.setFriction(250);

   ActionObject* ao = new ActionObject(m_playersManager, m_renderingManager, 
                                    new CRenderableObject(m_meshStorage.getLaserMesh(), D3DMATERIAL9()), 
                                    renderableEnemy);

   m_activePlayers.push_back(ao);

   m_aiAgents.push_back(new AIAgent(m_raceController, *ao, movableEnemy));

}

/////////////////////////////////////////////////////////////////////////////

void TrackLoader::addGate(const D3DXVECTOR3& pole1Pos, 
                   const D3DXVECTOR3& pole2Pos)
{
   D3DMATERIAL9 poleMat;
   ZeroMemory(&poleMat.Specular, sizeof(poleMat.Specular));
   ZeroMemory(&poleMat.Emissive, sizeof(poleMat.Emissive));
   poleMat.Diffuse.r = 0.4f; poleMat.Diffuse.g = 0.4f; poleMat.Diffuse.b = 0.4f;
   poleMat.Ambient.r = 0.2f; poleMat.Ambient.g = 0.2f; poleMat.Ambient.b = 0.2f;

   CRenderableObject* pole1 = new CRenderableObject(m_meshStorage.getPoleMesh(), poleMat);
   m_renderingManager.startRendering(*pole1);
   pole1->move(pole1Pos);
   PhysicalObject& pole1PhysObj = m_collisionController.addMovable(*pole1);

   CRenderableObject* pole2 = new CRenderableObject(m_meshStorage.getPoleMesh(), poleMat);
   m_renderingManager.startRendering(*pole2);
   pole2->move(pole2Pos);
   PhysicalObject& pole2PhysObj = m_collisionController.addMovable(*pole2);

   pole1PhysObj.setAcceleration(0);
   pole1PhysObj.setMaxHorizontalSpeed(0);
   pole1PhysObj.setMaxVerticalSpeed(0);
   pole1PhysObj.setWeight(100);

   pole2PhysObj.setAcceleration(0);
   pole2PhysObj.setMaxHorizontalSpeed(0);
   pole2PhysObj.setMaxVerticalSpeed(0);
   pole2PhysObj.setWeight(100);

   m_gates.push_back(new Gate(pole1, pole2));
}

/////////////////////////////////////////////////////////////////////////////
